﻿/*======================================================================
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
========================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BlueCurve.Algorithms
{
    public class Algorithms
    {
        #region 'Rank'
        
        /// <summary>
        /// Calcul l'indice de pertinence global du document
        /// en tenant compte de sa similarité entre la recherche et le document
        /// La formule est : facteur_amortissement * similarité + ( 1 - facteur_amortissement) * rang
        /// </summary>
        /// <param name="alphafactor">Facteur d'amortissement</param>
        /// <param name="similarity">Similarité entre le document et la recherche</param>
        /// <param name="rank">Importance du document sur le web</param>
        /// <returns>Indice de pertinence global du document</returns>
        public double RevelancePerRankAndSimilarity(float similarity, float rank, float alphafactor)
        {
            return ((alphafactor * similarity) + (1 - alphafactor) * rank);
        }

        /// <summary>
        /// Calcul la pertinence du document (web) en ce basant sur
        /// les liens hypertextes
        /// </summary>
        /// <param name="alphafactor">Facteur d'amortissement</param>
        /// <param name="outgoing">Nbre de liens sortants</param>
        /// <param name="ingoing">Nbre de liens entrants</param>
        /// <returns>Pagerank</returns>
        public double RevelanceRank(float alphafactor, int outgoing, int ingoing)
        {
            return ((1 - alphafactor) + alphafactor * (outgoing + ingoing));
        }

        /// <summary>
        /// Calcul la pertinence du document (web) en ce basant sur
        /// les liens hypertextes
        /// </summary>
        /// <param name="alphafactor">Facteur d'amortissement</param>
        /// <param name="linkeddocs">Documents liés</param>
        /// <returns>Pagerank</returns>
        public virtual double RevelanceRank(float alphafactor, Dictionary<double, int> linkeddocs)
        {
            double temp = 0;
            foreach (KeyValuePair<double, int> pair in linkeddocs)
                temp += (pair.Key / pair.Value);

            return ((1 - alphafactor) + alphafactor * temp);
        }

        #endregion




        #region 'Estimating frequency of changes'

        /// <summary>
        /// Estime la fréquence de changement d'un document
        /// </summary>
        /// <param name="numberofdetectedchanges">Nombre de changements détectés</param>
        /// <param name="numberofaccess">Nombre d'accès</param>
        /// <param name="sumoflastmodifieddates">Somme des dates de dernières modifications</param>
        /// <returns>double</returns>
        public double ChangeFreqEstimate(int numberofdetectedchanges, long numberofaccess, int sumoflastmodifieddates)
        {
            return (((numberofdetectedchanges - 1) - (numberofdetectedchanges / (numberofaccess * Math.Log(1 - numberofdetectedchanges / numberofdetectedchanges)))) / sumoflastmodifieddates);
        }
        
        /// <summary>
        /// Fonction appelée lors de l'accès a un document
        /// incrémente le nombre d'accès de 1
        /// mets a jour le nombres de changements détectés et
        /// la somme des dates "modifiés"
        /// </summary>
        /// <param name="lastmodifiedtime">Date du dernier changement</param>
        /// <param name="numberofaccess">Nombres d'accès au document</param>
        /// <param name="Ii">Interval(moyen) entre les accèss</param>
        /// <param name="numberofdetectedchanges">Nombres de changements détecté</param>
        /// <param name="sumoflastmodifieddates">Somme des dates de dernières modifications</param>
        public void ChangeFreqUpdate(DateTime lastmodifiedtime, ref int numberofaccess, int Ii, ref int numberofdetectedchanges, ref int sumoflastmodifieddates)
        {
            int Ti = (lastmodifiedtime.Minute - numberofaccess); // Ti = (last-modified time - access time) at ith access
            numberofaccess++;
            if (Ti < Ii)
            {
                numberofdetectedchanges += 1;
                sumoflastmodifieddates += Ti;
            }
            else
            {
                sumoflastmodifieddates += Ii;
            }
        }

        #endregion





        #region 'Synchronizing database to improve freshness'

        /// <summary>
        /// Calcul la fraicheur de la base de données
        /// </summary>
        /// <param name="numberofelementsinthedatabase">Nombre d'éléments dans la base de données</param>
        /// <param name="freshelements">Nombre d'éléments à jour</param>
        /// <returns>double</returns>
        public double FreshnessOfDatabase(long numberofelementsinthedatabase, double freshelements)
        {
            return ((1 / numberofelementsinthedatabase) * freshelements);
        }

        /// <summary>
        /// Calcul l'age de la base de données
        /// </summary>
        /// <param name="numberofelementsinthedatabase">Nombre d'éléments dans la base de données</param>
        /// <param name="agesoffreshelements">Somme des ages des éléments à jour</param>
        /// <returns>double</returns>
        public double AgeOfDatabase(long numberofelementsinthedatabase, double agesoffreshelements)
        {
            return ((1 / numberofelementsinthedatabase) * agesoffreshelements);
        }

        /// <summary>
        /// Calcul le ratio (r) de mise à jour
        /// d'un élement
        /// </summary>
        /// <param name="realworldelementchange">Nombre de fois ou l'élement à été mis a jour (en jours ou en mois)</param>
        /// <returns>float</returns>
        public float ElementUpdateFrequencyRatio(int realworldelementchange)
        {
            return (1 / realworldelementchange);
        }

        /// <summary>
        /// Calcul la fraicheur d'un element
        /// dans la politique demaj
        /// </summary>
        /// <param name="elementppdatefrequencyratio">Ratio de mise à jour</param>
        /// <returns>Fraicheur de l'élement</returns>
     /*   public double FixedOrderPolicyFreshness(long elementppdatefrequencyratio, long )
        {
            return (1 - (elementppdatefrequencyratio));
        }*/

        #endregion

    }
}
